use crate::time;
use core::alloc::Layout;
use core::time::Duration;

#[derive(Clone)]
#[repr(C)]
pub struct Attr {
    pub(crate) group_id: u8,
    pub(crate) priority: u8,
    pub(crate) fdset: u16,
    pub(crate) delay: bool,
    pub(crate) hash: usize,
    pub(crate) timeout: Duration,
    pub(crate) max_cache: usize,
    pub(crate) tail: Layout,
}

impl Default for Attr {
    fn default() -> Self {
        Self::new()
    }
}

impl Attr {
    /// 设置运行时的ID，ID对应的运行时必须已经启动
    pub const fn new() -> Self {
        Self {
            group_id: 0,
            priority: 0,
            fdset: 32,
            timeout: Duration::MAX,
            delay: false,
            hash: 0,
            max_cache: 0,
            tail: Layout::new::<()>(),
        }
    }

    /// 设置在哪个运行时实例中调度，设置的运行时必须已经创建成功
    pub fn id(&mut self, id: u8) -> &mut Self {
        self.group_id = id;
        self
    }

    /// 设置优先级, 当前只支持两个优先级，0代表普通，大于0代表高优先级
    pub fn priority(&mut self, priority: u8) -> &mut Self {
        self.priority = priority;
        self
    }

    /// 同一个task中最大可使用的AioFd数量，缺省32.
    /// 如果频繁有Fd关闭新建，关闭前调用AioFd::wait_none释放资源
    pub fn fdset(&mut self, capacity: u16) -> &mut Self {
        self.fdset = capacity;
        self
    }

    /// 设置hash值，如果非0，则会保证在hash对应的工作线程中调度
    /// 业务可以基于此hash值决定哪些任务在同一个工作线程中运行
    pub fn hash(&mut self, hash: usize) -> &mut Self {
        self.hash = hash;
        self
    }

    /// 设置任务最迟完成时间，如果在此时间还未完成，则会自动取消
    /// 参数timeout是基相对时间, 而非决对时间
    pub fn deadline(&mut self, timeout: Duration) -> &mut Self {
        self.timeout = timeout.saturating_add(time::now());
        self
    }

    /// 设置任务延迟调度时间
    /// 参数timeout是基相对时间, 而非决对时间
    pub fn delay(&mut self, timeout: Duration) -> &mut Self {
        self.delay = true;
        self.timeout = timeout;
        self
    }

    /// 仅对local::block_on_with接口有效
    /// 指定临时运行时支持task cache的最大值，缺省为0，表示不支持task cache.
    pub fn max_cache(&mut self, max_cache: usize) -> &mut Self {
        self.max_cache = max_cache;
        self
    }

    pub(crate) fn tail(&mut self, layout: Layout) -> &mut Self {
        self.tail = layout;
        self
    }
}
